package com.chainwintel.prjmgmt.action;

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.ExceptionMapping;
import org.apache.struts2.convention.annotation.ExceptionMappings;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.apache.struts2.interceptor.SessionAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;

import com.chainwintel.prjmgmt.exception.FailedToAssignOperationsException;
import com.chainwintel.prjmgmt.model.MenuItem;
import com.chainwintel.prjmgmt.model.User;
import com.chainwintel.prjmgmt.service.MenuItemMgr;
import com.chainwintel.prjmgmt.service.UserMgr;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;

@Component
@Results({
	@Result(name = "userForm", location = "userEditForm.jsp"),
	@Result(name = "listUsers", location = "/user/list", type = "redirectAction"),
	@Result(name = "userListPage", location = "userManagement.jsp"),
	@Result(name = "home", location = "home.jsp")
})
@ExceptionMappings({
	@ExceptionMapping(exception = "com.chainwintel.prjmgmt.exception.FailedToAssignOperationsException" ,result = "error.jsp"),
	@ExceptionMapping(exception = "java.lang.RuntimeException", result = "error.jsp"),
	@ExceptionMapping(exception = "java.lang.Exception" ,result = "error.jsp")
})
public class UserAction extends ActionSupport implements Preparable,SessionAware {

	/**
	 * serialVersionUID
	 */
	private static final long serialVersionUID = 1L;
	
	private static final Log log = LogFactory.getLog(UserAction.class);
	
	private List<User> users;
	
	private User user;
	
	private long userId = -1;
	
	private long operId;
	
	private Map<String, Object> sessionAttr;  
	

	


	@Autowired
	private UserMgr userMgr;
	
	@Autowired
	private MenuItemMgr menuItemMgr;

	private Set<MenuItem> menuList;

	private User currentUser;
	
	public void prepare() throws Exception {
		// TODO Auto-generated method stub
		try {
			setUsers(userMgr.listUsers());
			setCurrentUser((User) getSessionAttr().get("currentUser"));
		} catch (DataAccessException e) {
			// TODO Auto-generated catch block
			log.error("DataAccessException occurred.", e);
			
		}
	}

	@Action(value = "/user/edit/form")
	public String prepareUserForm() {
		// TODO Auto-generated method stub
		try {
			if (getUserId() < 0) {
				setUser(new User());
			} else {
				setUser(userMgr.find(getUserId()));
			}
			return "userForm";
		} catch (DataAccessException e) {
			// TODO Auto-generated catch block
			log.error("DataAccessException occurred", e);
			throw new RuntimeException("Operation failed.",e);
		}
	}
	
	@Action(value = "/user/edit/do") 
	public String doUserEdit() {
		try {
			userMgr.merge(getUser());
			return "listUsers";
		} catch (DataAccessException e) {
			// TODO Auto-generated catch block
			log.error("DataAccessException occurred", e);
			throw new RuntimeException("Operation failed.",e);
		}
	}
	
	@Action("/user/list")
	public String userList()  {
		return "userListPage";
	}

	@Action("/user/oper/assign")
	public String assignOperations() throws FailedToAssignOperationsException {
		try {
			MenuItem menuItem = menuItemMgr.find(getOperId());
			userMgr.assignOpers(menuItem,getCurrentUser());
			return "listUsers";
		} catch (DataAccessException e) {
			// TODO Auto-generated catch block
			log.error("Failed!! DataAccessException occurred!", e);
			throw new FailedToAssignOperationsException("Operation failed.",e);
		}
		
	}
	
	@Action("/user/menu/load")
	public String loadMenu() {
		try {
			setMenuList(userMgr.loadMenu(getCurrentUser()));
			return "home";
		} catch (DataAccessException e) {
			// TODO Auto-generated catch block
			log.error("DataAccessException occurred", e);
			throw new RuntimeException("Operation failed.",e);
		}
	}

	/**
	 * @param users the users to set
	 */
	public void setUsers(List<User> users) {
		this.users = users;
	}

	/**
	 * @return the users
	 */
	public List<User> getUsers() {
		return users;
	}

	/**
	 * @param user the user to set
	 */
	public void setUser(User user) {
		this.user = user;
	}

	/**
	 * @return the user
	 */
	public User getUser() {
		return user;
	}

	/**
	 * @param userId the userId to set
	 */
	public void setUserId(long userId) {
		this.userId = userId;
	}

	/**
	 * @return the userId
	 */
	public long getUserId() {
		return userId;
	}

	/**
	 * @param operId the operId to set
	 */
	public void setOperId(long operId) {
		this.operId = operId;
	}

	/**
	 * @return the operId
	 */
	public long getOperId() {
		return operId;
	}

	public void setSession(Map<String, Object> arg0) {
		// TODO Auto-generated method stub
		this.setSessionAttr(arg0);
	}

	/**
	 * @param sessionAttr the sessionAttr to set
	 */
	public void setSessionAttr(Map<String, Object> sessionAttr) {
		this.sessionAttr = sessionAttr;
	}

	/**
	 * @return the sessionAttr
	 */
	public Map<String, Object> getSessionAttr() {
		return sessionAttr;
	}

	/**
	 * @param menuList the menuList to set
	 */
	public void setMenuList(Set<MenuItem> menuList) {
		this.menuList = menuList;
	}

	/**
	 * @return the menuList
	 */
	public Set<MenuItem> getMenuList() {
		return menuList;
	}

	/**
	 * @param currentUser the currentUser to set
	 */
	public void setCurrentUser(User currentUser) {
		this.currentUser = currentUser;
	}

	/**
	 * @return the currentUser
	 */
	public User getCurrentUser() {
		return currentUser;
	}
}
